﻿using DongFangGuoKai.WCSPlatform.WebApi.Utils.UtilModel;
using S7.Net;

namespace DongFangGuoKai.WCSPlatform.WebApi.Extensions
{
    public static class PlcExtension
    {
        /// <summary>
        /// 读取字符串
        /// </summary>
        /// <param name="plc"></param>
        /// <param name="db">DB块</param>
        /// <param name="addr">偏移量</param>
        /// <returns></returns>
        public static string ReadString(this Plc plc, int db, double addr)
        {
            string addr1 = "DB" + db.ToString() + ".DBB" + (addr + 1).ToString();
            try
            {
                int len = int.Parse(plc.Read(addr1).ToString());
                string getstring = "";
                for (int i = 0; i < len; i++)
                {
                    string addr2 = "DB" + db.ToString() + ".DBB" + (addr + 2 + i).ToString();
                    string result = plc.Read(addr2).ToString();
                    int value = Convert.ToInt32(result, 10);
                    string stringValue = Char.ConvertFromUtf32(value);
                    getstring += stringValue;
                }
                return getstring;
            }
            catch (PlcException ex)
            {
                plc.Close();
                return string.Empty;
            }
        }
        /// <summary>
        /// 写入字符串
        /// </summary>
        /// <param name="plc"></param>
        /// <param name="db">DB块</param>
        /// <param name="addr">偏移量</param>
        /// <param name="data">数据</param>
        public static void WriteString(this Plc plc, int db, double addr, string data)
        {
            try
            {
                byte len = Convert.ToByte(data.Length);
                string addr1 = "DB" + db.ToString() + ".DBB" + (addr + 1).ToString();
                plc.Write(addr1, len);
                char[] single = data.ToCharArray();
                for (int i = 0; i < data.Length; i++)
                {
                    string addr2 = "DB" + db.ToString() + ".DBB" + (addr + 2 + i).ToString();
                    plc.Write(addr2, single[i].ToString());
                }
            }
            catch (Exception)
            {
                plc.Close();
            }
        }
        /// <summary>
        /// 检测有没有写入成功
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="plc"></param>
        /// <param name="writeResIs"></param>
        /// <returns>true:成功 false:失败</returns>
        public static bool CheckWriteRes<T>(this Plc plc, WriteResIs<T> writeResIs)
        {
            try
            {
                var readVal = (T)plc.Read(writeResIs.dbAddress);
                return EqualityComparer<T>.Default.Equals(readVal, writeResIs.val);//泛型比较器
            }
            catch (Exception)
            {
                plc.Close();
                throw;
            }
        }

        /// <summary>
        /// 检测一组写入是否成功
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="plc"></param>
        /// <param name="writeResAre"></param>
        /// <returns></returns>
        public static bool CheckWriteRes<T>(this Plc plc, List<WriteResIs<T>> writeResAre)
        {
            foreach (var writeResIs in writeResAre)
            {
                var readVal = (T)plc.Read(writeResIs.dbAddress);
                if (!EqualityComparer<T>.Default.Equals(readVal, writeResIs.val)) return false;
            }
            return true;
        }
        /// <summary>
        /// 带有检查的写入方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="plc"></param>
        /// <param name="dbAddress"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static bool WriteIs<T>(this Plc plc,string dbAddress,T val)
        {
            try
            {
                plc.Write(dbAddress, val);
                return CheckWriteRes(plc, new WriteResIs<T>(dbAddress, val));
            }
            catch (Exception)
            {
                plc.Close();
                throw;
            }
        }
        /// <summary>
        /// 带有检查的写入方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="plc"></param>
        /// <param name="dbAddress"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public static async Task<bool> WriteIsAsync<T>(this Plc plc, string dbAddress, T val)
        {
            try
            {
                await plc.WriteAsync(dbAddress, val);
                return CheckWriteRes(plc, new WriteResIs<T>(dbAddress, val));
            }
            catch (Exception)
            {
                plc.Close();
                throw;
            }
        }
        /// <summary>
        /// 开启plc连接
        /// </summary>
        /// <param name="plc"></param>
        /// <returns></returns>
        public static bool PlcStart(this Plc plc)
        {
            try
            {
                plc.Open();
                return plc.IsConnected;
            }
            catch (PlcException)
            {

                throw;
            }
        }
        /// <summary>
        /// 关闭Plc连接
        /// </summary>
        /// <param name="plc"></param>
        /// <returns></returns>
        public static bool PlcStop(this Plc plc)
        {
            try
            {
                plc.Close();
                return !plc.IsConnected;
            }
            catch (PlcException)
            {

                throw;
            }
        }
    }
}
